package com.huaxin.hxenum.utils;

import com.huaxin.hxenum.base.BaseCodeEnum;
import com.huaxin.hxenum.base.Colorful;
import com.huaxin.hxenum.base.Describable;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 枚举工具类：用于生成前端所需的下拉选项、描述、颜色等
 *
 * @author YourName
 * @date 2025-09-24
 */
public final class EnumUtils {

    private EnumUtils() {
        throw new AssertionError("No instances for utility class");
    }

    // ==================== 通用选项 DTO ====================

    /**
     * 前端下拉框选项标准结构
     */
    public static class Option {
        private final Object value;      // 对应枚举的 code
        private final String displayName;      // 对应 displayName
        private final String description; // 描述（可选）
        private final String color;      // 颜色（可选）

        public Option(Object value, String displayName) {
            this(value, displayName, null, null);
        }

        public Option(Object value, String displayName, String description, String color) {
            this.value = value;
            this.displayName = displayName;
            this.description = description;
            this.color = color;
        }

        // --- Getters ---
        public Object getValue() {
            return value;
        }

        public String getDisplayName() {
            return displayName;
        }

        public String getDescription() {
            return description;
        }

        public String getColor() {
            return color;
        }
    }

    // ==================== 核心转换方法 ====================

    /**
     * 通用方法：将任意 BaseCodeEnum 枚举转换为选项列表
     * 支持链式扩展：Describable, Colorful
     *
     * @param enumClass 枚举类
     * @param <E>       枚举类型
     * @param <T>       code 类型
     * @return 选项列表
     */
    public static <E extends Enum<E> & BaseCodeEnum<T>, T> List<Option> toOptions(Class<E> enumClass) {
        return Arrays.stream(enumClass.getEnumConstants())
                .map(enumInstance -> {
                    String description = null;
                    String color = null;

                    if (enumInstance instanceof Describable d) {
                        description = d.getDescription();
                    }
                    if (enumInstance instanceof Colorful c) {
                        color = c.getColor();
                    }

                    return new Option(enumInstance.getCode(), enumInstance.getDisplayName(), description, color);
                })
                .collect(Collectors.toList());
    }

    /**
     * 仅提取 displayName 和 value（最简下拉框）
     */
    public static <E extends Enum<E> & BaseCodeEnum<T>, T> List<Option> toSimpleOptions(Class<E> enumClass) {
        return Arrays.stream(enumClass.getEnumConstants())
                .map(e -> new Option(e.getCode(), e.getDisplayName()))
                .collect(Collectors.toList());
    }

    // ==================== 便捷方法（按接口筛选） ====================

    /**
     * 只包含描述的选项
     */
    public static <E extends Enum<E> & BaseCodeEnum<T> & Describable, T> List<Option> toDescriptiveOptions(Class<E> enumClass) {
        return Arrays.stream(enumClass.getEnumConstants())
                .map(e -> new Option(e.getCode(), e.getDisplayName(), e.getDescription(), null))
                .collect(Collectors.toList());
    }

    /**
     * 只包含颜色的选项
     */
    public static <E extends Enum<E> & BaseCodeEnum<T> & Colorful, T> List<Option> toColorfulOptions(Class<E> enumClass) {
        return Arrays.stream(enumClass.getEnumConstants())
                .map(e -> new Option(e.getCode(), e.getDisplayName(), null, e.getColor()))
                .collect(Collectors.toList());
    }

    // ==================== 工具方法 ====================

    /**
     * 根据 code 查找枚举实例
     */
    public static <E extends Enum<E> & BaseCodeEnum<T>, T> Optional<E> fromCode(Class<E> enumClass, T code) {
        return Arrays.stream(enumClass.getEnumConstants())
                .filter(e -> Objects.equals(e.getCode(), code))
                .findFirst();
    }

    /**
     * 获取所有枚举的 code 列表（用于校验）
     */
    public static <E extends Enum<E> & BaseCodeEnum<T>, T> Set<T> getAllCodes(Class<E> enumClass) {
        return Arrays.stream(enumClass.getEnumConstants())
                .map(BaseCodeEnum::getCode)
                .collect(Collectors.toSet());
    }

    /**
     * 转为 Map<code, displayName>（用于日志、显示）
     */
    public static <E extends Enum<E> & BaseCodeEnum<T>, T> Map<T, String> toDisplayNameMap(Class<E> enumClass) {
        return Arrays.stream(enumClass.getEnumConstants())
                .collect(Collectors.toMap(BaseCodeEnum::getCode, BaseCodeEnum::getDisplayName));
    }

    /**
     * 校验整数列表是否都属于某个枚举的指定字段值
     *
     * @param enumClass      枚举类
     * @param valueExtractor 提取枚举中对应整数值的函数
     * @param values         待校验的整数列表
     * @param <T>            枚举类型
     * @return 是否全部有效
     */
    public static <T extends Enum<T>> boolean isValidValues(
            Class<T> enumClass,
            Function<T, Integer> valueExtractor,
            List<Integer> values) {

        if (values == null || values.isEmpty()) {
            return false;
        }

        Set<Integer> validValues = Arrays.stream(enumClass.getEnumConstants())
                .map(valueExtractor)
                .collect(Collectors.toSet());

        return validValues.containsAll(values);
    }
}